<template>
    <div>
        <el-button type="primary" @click="clickAnimationStart">刷新动画</el-button>
        <div class="home">

            <!--        运动的dom-->
            <div id="box"></div>
            <!--        属性配置-->
            <div class="config_box">
                <div class="item_box">
                    <span>动画</span>
                    <el-switch v-model="config.sfAnimation"/>
                </div>
                <div class="item_box">
                    <span>循环播放</span>
                    <el-switch v-model="config.sfLoop"/>
                </div>
                <div class="item_box">
                    <span>动画时长</span>
                    <el-input-number v-model="config.durationTimes"/>
                </div>
                <div class="item_box">
                    <span>延迟时间</span>
                    <el-input-number v-model="config.delayTimes"/>
                </div>
                <div class="item_box">
                    <span>间隔时间</span>
                    <el-input-number v-model="config.intervalTimes"/>
                </div>
                <el-button type="primary" @click="plusKeyframes">添加关键帧</el-button>
                <div v-for="(item,index) in config.keyframesList" :key="index">
                    <div>关键帧{{ index + 1 }}</div>
                    <div class="item_box">
                        <span style="width: 150px">所处时间轴</span>
                        <el-slider v-model="item.timeAxis"/>
                    </div>
                    <div class="item_box">
                        <span style="width: 150px">透明度</span>
                        <el-slider v-model="item.opacity"/>
                    </div>
                    <div class="item_box">
                        <span style="width: 150px">旋转</span>
                        <el-switch v-model="item.sfRotate"/>
                    </div>
                    <div v-if="item.sfRotate">
                        <div class="item_box">
                            <span style="width: 150px" >绕X轴</span>
                            <el-slider v-model="item.rotateX" :min="-180" :max="180"/>
                        </div>
                        <div class="item_box">
                            <span style="width: 150px">绕Y轴</span>
                            <el-slider v-model="item.rotateY"  :min="-180" :max="180"/>
                        </div>
                        <div class="item_box">
                            <span style="width: 150px" >绕Z轴</span>
                            <el-slider v-model="item.rotateZ" :min="-180" :max="180"/>
                        </div>
                    </div>
                    <div class="item_box">
                        <span style="width: 150px">缩放</span>
                        <el-switch v-model="item.sfScale"/>
                    </div>
                    <div v-if="item.sfScale">
                        <div class="item_box">
                            <span style="width: 150px">X轴方向</span>
                            <el-input-number
                                v-model="item.scaleX"
                                controls-position="right"
                            />
                        </div>
                        <div class="item_box">
                            <span style="width: 150px">Y轴方向</span>
                            <el-input-number
                                v-model="item.scaleY"
                                controls-position="right"
                            />
                        </div>
                    </div>
                    <div class="item_box">
                        <span style="width: 150px">平移</span>
                        <el-switch v-model="item.sfTranslate"/>
                    </div>
                    <div v-if="item.sfTranslate">
                        <div class="item_box">
                            <span style="width: 150px">X轴方向</span>
                            <el-input-number
                                v-model="item.translateX"
                                controls-position="right"
                            />
                        </div>
                        <div class="item_box">
                            <span style="width: 150px">Y轴方向</span>
                            <el-input-number
                                v-model="item.translateY"
                                controls-position="right"
                            />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
import {ref, onMounted, computed} from 'vue'
import {floatRound} from '@/utils'
import {AnimationClass} from '@/utils/animationFun'
//放动画效果
let anim = ref([])
let animationClass = ref(null);
let timer = ref(null);
let config = ref({
    sfAnimation: false, // 是否开启动画
    sfLoop: false, //是否循环播放
    durationTimes: 5, //动画时长
    delayTimes: 5, //延迟时间
    intervalTimes: 5,  //动画间隔时间
    keyframesList: [] //关键帧
})
const plusKeyframes = () => {
    config.value.keyframesList.push({
        timeAxis: 100,//所处时间轴
        opacity: 100, //透明度
        sfRotate: false, //是否旋转
        rotateX: 0,
        rotateY: 0,
        rotateZ: 0,
        sfScale: false, //是否缩放
        scaleX: 100,
        scaleY: 100,
        sfTranslate: false, //是否平移
        translateX: 0,
        translateY: 0,

    })
}
const animationConfig = computed(() => {
    return {
        durationTimes: config.value.durationTimes * 1000, //动画时长
        delayTimes: config.value.delayTimes * 1000, //延迟时间
        intervalTimes: config.value.intervalTimes * 1000,  //动画间隔时间
    }
})
const keyframeConfig = computed(() => {
    return config.value.keyframesList
})

//多组合动画效果
const multipleAnimationFun = () => {
    let list = [] //添加关键帧信息
    timer.value && clearInterval(timer.value)
    // 销毁时清楚动画效果
    animationClass.value && animationClass.value.destroy()
    //定义一套初始时的关键帧数据，如果第一帧是 0 帧那么走设置的效果，否则走初始值的效果
    let initData = {
        opacity: '1',
        rotateX: '0deg',
        rotateY: '0deg',
        rotateZ: '0deg',
        scaleX: '1',
        scaleY: '1',
        translateX: '0px',
        translateY: '0px'
    }
    // 如果定义的第一帧是0帧，那么初始值是0帧对应的值
    if (keyframeConfig.value[0].timeAxis === 0) {
        initData.opacity = floatRound(keyframeConfig.value[0].opacity / 100, 5) + ''
        initData.rotateX = keyframeConfig.value[0].rotateX
        initData.rotateY = keyframeConfig.value[0].rotateY
        initData.rotateZ = keyframeConfig.value[0].rotateZ
        initData.scaleX = keyframeConfig.value[0].scaleX
        initData.scaleY = keyframeConfig.value[0].scaleY
        initData.translateX = keyframeConfig.value[0].translateX
        initData.translateY = keyframeConfig.value[0].translateY
    }
    if (keyframeConfig.value.length === 1) {
        anim.value = [
            {
                dom: document.getElementById('box'),
                anim: [
                    {
                        style: 'opacity',
                        from: initData.opacity,
                        to: floatRound(keyframeConfig.value[0].opacity / 100, 5) + '',
                        start: 0,
                        end: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[0].timeAxis / 100),
                    },
                    {
                        style: 'opacity',
                        from: floatRound(keyframeConfig.value[0].opacity / 100, 5) + '',
                        to: floatRound(keyframeConfig.value[0].opacity / 100, 5) + '',
                        start: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[0].timeAxis / 100),
                        end: animationConfig.value.durationTimes,
                    },
                    {
                        style: 'transform',
                        from: `rotateX(${initData.rotateX}) rotateY(${initData.rotateY}) rotateZ(${initData.rotateZ}) scaleX(${initData.scaleX}) scaleY(${initData.scaleY}) translateX(${initData.translateX}) translateY(${initData.translateY})`,
                        to: `rotateX(${keyframeConfig.value[0].sfRotate ? keyframeConfig.value[0].rotateX : '0'}deg) rotateY(${keyframeConfig.value[0].sfRotate ? keyframeConfig.value[0].rotateY : '0'}deg) rotateZ(${keyframeConfig.value[0].sfRotate ? keyframeConfig.value[0].rotateZ : '0'}deg) scaleX(${keyframeConfig.value[0].sfScale ? floatRound(keyframeConfig.value[0].scaleX / 100, 5) : '1'}) scaleY(${keyframeConfig.value[0].sfScale ? floatRound(keyframeConfig.value[0].scaleY / 100, 5) : '1'}) translateX(${keyframeConfig.value[0].sfTranslate ? keyframeConfig.value[0].translateX : '0'}px) translateY(${keyframeConfig.value[0].sfTranslate ? keyframeConfig.value[0].translateY : '0'}px)`,
                        start: 0,
                        end: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[0].timeAxis / 100),
                    },
                ]
            }
        ]
    }
    if (keyframeConfig.value.length > 1) {
        //添加初始帧，在上面已经处理过第一帧是否为0帧的初始化数据
        list = [
            {
                style: 'opacity',
                from: floatRound(keyframeConfig.value[keyframeConfig.value.length - 1].opacity / 100, 5) + '',
                to: floatRound(keyframeConfig.value[0].opacity / 100, 5) + '',
                start: 0,
                end: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[0].timeAxis / 100),
            },
            {
                style: 'transform',
                to: `rotateX(${keyframeConfig.value[0].sfRotate ? keyframeConfig.value[0].rotateX : '0'}deg) rotateY(${keyframeConfig.value[0].sfRotate ? keyframeConfig.value[0].rotateY : '0'}deg) rotateZ(${keyframeConfig.value[0].sfRotate ? keyframeConfig.value[0].rotateZ : '0'}deg) scaleX(${keyframeConfig.value[0].sfScale ? floatRound(keyframeConfig.value[0].scaleX / 100, 5) : '1'}) scaleY(${keyframeConfig.value[0].sfScale ? floatRound(keyframeConfig.value[0].scaleY / 100, 5) : '1'}) translateX(${keyframeConfig.value[0].sfTranslate ? keyframeConfig.value[0].translateX : '0'}px) translateY(${keyframeConfig.value[0].sfTranslate ? keyframeConfig.value[0].translateY : '0'}px)`,
                from: 'rotateX(0deg) rotateY(0deg) rotateZ(0deg) scaleX(1) scaleY(1) translateX(0px) translateY(0px)',
                start: 0,
                end: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[0].timeAxis / 100),
            }
        ]
        keyframeConfig.value.forEach((item, index) => {
            //去掉第一帧跟最后一帧，需要做关键处理
            if (index > 0 && index !== keyframeConfig.value.length - 1) {
                if (keyframeConfig.value[index - 1].timeAxis < item.timeAxis) {
                    list.push(
                        {
                            style: 'opacity',
                            from: floatRound(keyframeConfig.value[index - 1].opacity / 100, 5) + '',
                            to: floatRound(item.opacity / 100, 5) + '',
                            start: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[index - 1].timeAxis / 100),
                            end: floatRound(animationConfig.value.durationTimes * item.timeAxis / 100),
                        },
                        {
                            style: 'transform',
                            to: `rotateX(${item.sfRotate ? item.rotateX : keyframeConfig.value[index - 1].rotateX}deg) rotateY(${item.sfRotate ? item.rotateY : keyframeConfig.value[index - 1].rotateY}deg) rotateZ(${item.sfRotate ? item.rotateZ : keyframeConfig.value[index - 1].rotateZ}deg) scaleX(${item.sfScale ? floatRound(item.scaleX / 100, 5) : floatRound(keyframeConfig.value[index - 1].scaleX / 100, 5)}) scaleY(${item.sfScale ? floatRound(item.scaleY / 100, 5) : floatRound(keyframeConfig.value[index - 1].scaleY / 100, 5)}) translateX(${item.sfTranslate ? item.translateX : keyframeConfig.value[index - 1].translateX}px) translateY(${item.sfTranslate ? item.translateY : keyframeConfig.value[index - 1].translateY}px)`,
                            from: `rotateX(${keyframeConfig.value[index - 1].sfRotate ? keyframeConfig.value[index - 1].rotateX : '0'}deg) rotateY(${keyframeConfig.value[index - 1].sfRotate ? keyframeConfig.value[index - 1].rotateY : '0'}deg) rotateZ(${keyframeConfig.value[index - 1].sfRotate ? keyframeConfig.value[index - 1].rotateZ : '0'}deg) scaleX(${keyframeConfig.value[index - 1].sfScale ? floatRound(keyframeConfig.value[index - 1].scaleX / 100, 5) : '1'}) scaleY(${keyframeConfig.value[index - 1].sfScale ? floatRound(keyframeConfig.value[index - 1].scaleY / 100, 5) : '1'}) translateX(${keyframeConfig.value[index - 1].sfTranslate ? keyframeConfig.value[index - 1].translateX : '0'}px) translateY(${keyframeConfig.value[index - 1].sfTranslate ? keyframeConfig.value[index - 1].translateY : '0'}px)`,
                            start: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[index - 1].timeAxis / 100),
                            end: floatRound(animationConfig.value.durationTimes * item.timeAxis / 100),
                        },
                    )
                }
            }
            if (index === keyframeConfig.value.length - 1) {
                // 如果最后一项的时间轴不为100 ，那么需要添加一个从执行完最后一项到动画执行完的稳定过程
                if (item.timeAxis !== 100) {
                    //如果最后一个时间大于前一个时间
                    if (item.timeAxis > keyframeConfig.value[index - 1].timeAxis) {
                        list.push(
                            {
                                style: 'opacity',
                                from: floatRound(item.opacity / 100, 5) + '',
                                to: floatRound(item.opacity / 100, 5) + '',
                                start: floatRound(animationConfig.value.durationTimes * item.timeAxis / 100),
                                end: animationConfig.value.durationTimes,
                            },
                            {
                                style: 'transform',
                                to: `rotateX(${item.sfRotate ? item.rotateX : item.rotateX}deg) rotateY(${item.sfRotate ? item.rotateY : item.rotateY}deg) rotateZ(${item.sfRotate ? item.rotateZ : item.rotateZ}deg) scaleX(${item.sfScale ? floatRound(item.scaleX / 100, 5) : floatRound(item.scaleX / 100, 5)}) scaleY(${item.sfScale ? floatRound(item.scaleY / 100, 5) : floatRound(item.scaleY / 100, 5)}) translateX(${item.sfTranslate ? item.translateX : item.translateX}px) translateY(${item.sfTranslate ? item.translateY : item.translateY}px)`,
                                from: `rotateX(${item.sfRotate ? item.rotateX : item.rotateX}deg) rotateY(${item.sfRotate ? item.rotateY : item.rotateY}deg) rotateZ(${item.sfRotate ? item.rotateZ : item.rotateZ}deg) scaleX(${item.sfScale ? floatRound(item.scaleX / 100, 5) : floatRound(item.scaleX / 100, 5)}) scaleY(${item.sfScale ? floatRound(item.scaleY / 100, 5) : floatRound(item.scaleY / 100, 5)}) translateX(${item.sfTranslate ? item.translateX : item.translateX}px) translateY(${item.sfTranslate ? item.translateY : item.translateY}px)`,
                                start: floatRound(animationConfig.value.durationTimes * item.timeAxis / 100),
                                end: animationConfig.value.durationTimes,
                            },
                        )
                    } else {
                        //如果最后一个时间小于前一个时间
                        list.push(
                            {
                                style: 'opacity',
                                from: floatRound(item.opacity / 100, 5) + '',
                                to: floatRound(item.opacity / 100, 5) + '',
                                start: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[index - 1].timeAxis / 100),
                                end: animationConfig.value.durationTimes,
                            },
                            {
                                style: 'transform',
                                to: `rotateX(${item.sfRotate ? item.rotateX : item.rotateX}deg) rotateY(${item.sfRotate ? item.rotateY : item.rotateY}deg) rotateZ(${item.sfRotate ? item.rotateZ : item.rotateZ}deg) scaleX(${item.sfScale ? floatRound(item.scaleX / 100, 5) : floatRound(item.scaleX / 100, 5)}) scaleY(${item.sfScale ? floatRound(item.scaleY / 100, 5) : floatRound(item.scaleY / 100, 5)}) translateX(${item.sfTranslate ? item.translateX : item.translateX}px) translateY(${item.sfTranslate ? item.translateY : item.translateY}px)`,
                                from: `rotateX(${keyframeConfig.value[index - 1].sfRotate ? keyframeConfig.value[index - 1].rotateX : keyframeConfig.value[index - 1].rotateX}deg) rotateY(${keyframeConfig.value[index - 1].sfRotate ? keyframeConfig.value[index - 1].rotateY : keyframeConfig.value[index - 1].rotateY}deg) rotateZ(${keyframeConfig.value[index - 1].sfRotate ? keyframeConfig.value[index - 1].rotateZ : keyframeConfig.value[index - 1].rotateZ}deg) scaleX(${keyframeConfig.value[index - 1].sfScale ? floatRound(keyframeConfig.value[index - 1].scaleX / 100, 5) : floatRound(keyframeConfig.value[index - 1].scaleX / 100, 5)}) scaleY(${keyframeConfig.value[index - 1].sfScale ? floatRound(keyframeConfig.value[index - 1].scaleY / 100, 5) : floatRound(keyframeConfig.value[index - 1].scaleY / 100, 5)}) translateX(${keyframeConfig.value[index - 1].sfTranslate ? keyframeConfig.value[index - 1].translateX : keyframeConfig.value[index - 1].translateX}px) translateY(${keyframeConfig.value[index - 1].sfTranslate ? keyframeConfig.value[index - 1].translateY : keyframeConfig.value[index - 1].translateY}px)`,
                                start: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[index - 1].timeAxis / 100),
                                end: animationConfig.value.durationTimes,
                            },
                        )
                    }

                } else {
                    let maxIndex = 0
                    let maxEndTime = 0
                    //最后一个元素是100
                    keyframeConfig.value.forEach((item, index) => {
                        if (index !== keyframeConfig.value.length - 1) {
                            if (item.timeAxis > maxEndTime) {
                                maxEndTime = item.timeAxis
                                maxIndex = index
                            }
                        }
                    })
                    list.push(
                        {
                            style: 'opacity',
                            from: floatRound(keyframeConfig.value[maxIndex].opacity / 100, 5) + '',
                            to: floatRound(item.opacity / 100, 5) + '',
                            start: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[maxIndex].timeAxis / 100),
                            end: floatRound(animationConfig.value.durationTimes * item.timeAxis / 100),
                        },
                        {
                            style: 'transform',
                            to: `rotateX(${item.sfRotate ? item.rotateX : item.rotateX}deg) rotateY(${item.sfRotate ? item.rotateY : item.rotateY}deg) rotateZ(${item.sfRotate ? item.rotateZ : item.rotateZ}deg) scaleX(${item.sfScale ? floatRound(item.scaleX / 100, 5) : floatRound(item.scaleX / 100, 5)}) scaleY(${item.sfScale ? floatRound(item.scaleY / 100, 5) : floatRound(item.scaleY / 100, 5)}) translateX(${item.sfTranslate ? item.translateX : item.translateX}px) translateY(${item.sfTranslate ? item.translateY : item.translateY}px)`,
                            from: `rotateX(${keyframeConfig.value[maxIndex].sfRotate ? keyframeConfig.value[maxIndex].rotateX : '0'}deg) rotateY(${keyframeConfig.value[maxIndex].sfRotate ? keyframeConfig.value[maxIndex].rotateY : '0'}deg) rotateZ(${keyframeConfig.value[maxIndex].sfRotate ? keyframeConfig.value[maxIndex].rotateZ : '0'}deg) scaleX(${keyframeConfig.value[maxIndex].sfScale ? floatRound(keyframeConfig.value[maxIndex].scaleX / 100, 5) : '1'}) scaleY(${keyframeConfig.value[maxIndex].sfScale ? floatRound(keyframeConfig.value[maxIndex].scaleY / 100, 5) : '1'}) translateX(${keyframeConfig.value[maxIndex].sfTranslate ? keyframeConfig.value[maxIndex].translateX : '0'}px) translateY(${keyframeConfig.value[maxIndex].sfTranslate ? keyframeConfig.value[maxIndex].translateY : '0'}px)`,
                            start: floatRound(animationConfig.value.durationTimes * keyframeConfig.value[maxIndex].timeAxis / 100),
                            end: floatRound(animationConfig.value.durationTimes * item.timeAxis / 100),
                        },
                    )
                }
            }
        })
        anim.value = [
            {
                dom: document.getElementById('box'),
                anim: list
            }
        ]
    }
    //调用动画方法
    handleAnimationFun()
}

const handleAnimationFun = () => {
    timer.value = setTimeout(() => {
        animationClass.value = new AnimationClass({
            arr: anim.value,
            sfLoopPlay: config.value.sfLoop,
            intervalTime: animationConfig.value.intervalTimes
        })
        animationClass.value.animate()

    }, animationConfig.value.delayTimes)
}

//点击开始动画效果
const clickAnimationStart = () => {
    timer.value && clearInterval(timer.value)
    // 销毁时清楚动画效果
    animationClass.value && animationClass.value.destroy()
    if (config.value.keyframesList.length > 0 && config.value.sfAnimation) {
        multipleAnimationFun()
    }
}


</script>
<style lang="scss" scoped>
.home {
    display: flex;
    align-items: flex-start;
    position: relative;

    .config_box {
        width: 300px;
        position: absolute;
        right: 0;
        background-color: aliceblue;
        padding: 10px;

        .item_box {
            width: 100%;
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 7px;
        }
    }
}

#box {
    width: 300px;
    height: 300px;
    background-color: #409eff;
}
</style>